<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BasketSessionBased
 *
 * @author aneto
 */
class BasketSessionBased extends myBasket
{

  /** add product to session basket */
  public function addProduct($productID, $qty = 1)
  {
	if (!Doctrine::getTable('Product')->find($productID))
	  return false;

	if ($qty <= 0
	  )$qty = 1;

	$products = array();
	if ($this->getUser()->hasAttribute('basket.products'))
	{
	  $products = $this->getUser()->getAttribute('basket.products');
	}

	$qty = isset($products[$productID]) && is_integer((int) $products[$productID]) ? $products[$productID] + $qty : $qty;
	$this->changeAmount($productID, $qty);

	return true;
  }

  public function setShippingAddress($data)
  {
	$this->getUser()->setAttribute('basket.shipping.address', $data);
  }

  public function setBillingAddress($data)
  {
	$this->getUser()->setAttribute('basket.billing.address', $data);
  }

  public function getShippingAddress()
  {
	return $this->getAddress('shipping');
  }

  public function getBillingAddress()
  {
	return $this->getAddress('billing');
  }

  protected function getAddress($type)
  {
	$address = $this->getUser()->getAttribute("basket.$type.address", array());

	// if user is authenticated then return first address of apropriate type
	if (empty($address) && $this->getUser()->isAuthenticated())
	{
	  $address = Doctrine::getTable('PublicUserAddresses')->findOneByTypeAndPublicUserId(
			  $type,
			  $this->getUser()->getObject()->getId()
	  );

	  if ($address)
	  {
		return $address->toArray();
	  }
	  else
	  {
		return array();
	  }
	}
	return $address;
  }

  public function renderShippingAddress()
  {
	return $this->renderAddress($this->getShippingAddress());
  }

  public function renderBillingAddress()
  {
	return $this->renderAddress($this->getShippingAddress());
  }

  protected function renderAddress($address)
  {
	return sprintf('%s, %s, %s, %s, %s', $address['address'], $address['city'], $address['state'], $address['zip'], $address['country']);
  }

  public function setShippingZone($zoneID)
  {
	$this->getUser()->setAttribute('basket.products.shipping.zone', $zoneID);
  }

  public function price($type = myBasket::TOTAL_PAYABLE)
  {
	$result = 0;

	switch ($type)
	{
	  case myBasket::TOTAL_PAYABLE:
		$result = $this->getTotalPayable();
		break;
	  case myBasket::TOTAL_NO_SHIPPING:
		$result = $this->getTotalPrice();
		break;
	  case myBasket::SHIPPING_PRICE:
		$result = $this->getShippingPrice();
		break;
	  default:
		throw new Exception('wrong price type');
	}

	return $result;
  }

  public function getShippingZone()
  {
	return $this->getUser()->getAttribute('basket.products.shipping.zone');
  }

  public function renderShippingZone()
  {
	$zone = Doctrine::getTable('ShippingZone')->find($this->getShippingZone());

	return $zone['name'];
  }

  public function getProducts()
  {
	return $this->getUser()->getAttribute('basket.products', array());
  }

  public function getProductAmount($productID)
  {
	$products = $this->getProducts();
	return isset($products[$productID]) && is_integer((int) $products[$productID]) ? $products[$productID] : 0;
  }

  public function prepareDataForView()
  {
	$result = array();

	$basketInfo = $this->getProducts();
	$ids = array(-1);
	foreach ($basketInfo as $id => $val)
	{
	  $ids[] = $id;
	}

	$q = Doctrine::getTable('Product')->createQuery('basketProds')
			->from('Product p')
			->innerJoin('p.Translation t')
			->leftJoin('p.ProductPictures pp')
			->orderBy('p.pri asc')
			->addOrderBy('pp.pri asc')
			->whereIn('p.id', $ids);

	foreach ($q->execute() as $item)
	{
	  $result[] = new myBasketItem($item, $basketInfo[$item->getId()]);
	}

	return $result;
  }

  public function setTransportMethod($methodID)
  {
	$this->getUser()->setAttribute('basket.products.transport.method', $methodID);
  }

  public function getTransportMethod()
  {
	return $this->getUser()->getAttribute('basket.products.transport.method');
  }

  public function getAvailableTransportMethods()
  {
	$products = $this->getProducts();
	$total_mass = null;
	foreach ($products as $id => $count)
	{
	  //$prod = Doctrine::getTable('Product')->find($id);
	  $param = Doctrine_Query::create()
				->from('ParameterProductValue ppv')
				->select('ppv.common_value')
				->where('product_id = ?', $id)
				->andWhere('param_id = ?', 9) //hardcoded id for mass
				->execute()
				->getFirst(); 
	  $total_mass += $param['common_value'] * $count;
	}
	$methods = Doctrine_Query::create()
			->from('TransportType tt')
			->select('tt.*, ztt.*, sz.*')
			->innerJoin('tt.ShippingZones sz')
			->where('tt.max_weight >= ?', (int) $total_mass)
			->andWhere('sz.max_weight >= ?', (int) $total_mass)
			->andWhere('tt.min_weight <= ?', (int)$total_mass)
			->andWhere('sz.min_weight <= ?', (int)$total_mass)
			->execute();
	return $methods;
  }

  public function shippingCost($zoneID = false)
  {
	if (!$zoneID)
	{
	  $zoneID = $this->getShippingZone();
	}
	$interval = $this->shippingZoneInterval($zoneID);
	return $interval['price'];
  }

  public function shippingZoneInterval($zoneID = false)
  {
	if (!$zoneID)
	{
	  $zoneID = $this->getShippingZone();
	}
	if ($zoneID)
	{
	  $mass = $this->getOrderMass();
	  foreach (Doctrine::getTable('ShippingZone')->find($zoneID)->Intervals as $interval)
	  {
		if ($interval['start'] <= $mass && $interval['end'] >= $mass)
		  return $interval;
	  }
	}
	return array('start' => 0, 'end' => 1000000000, 'price' => 0);
  }

  private function getOrderMass()
  {
	return 200;
  }

  private function getShippingPrice()
  {
	return $this->shippingCost();
  }

  public function getTotalPayable()
  {
	$prodPrice = $this->getTotalPrice();
	if ($discount = $this->getDiscount())
	{
	  $disc = (100 - (int) $discount) / 100;
	  $prodPrice *= $disc;
	}
	return $this->getShippingPrice() + $prodPrice;
  }

  public function countItems()
  {
	$result = 0;

	foreach ($this->getProducts() as $id => $q)
	{
	  $result += $q;
	}

	return $result;
  }

  public function deleteProduct($id)
  {
	$ar = $this->getProducts();
	unset($ar[$id]);

	$this->setProducts($ar);
	return true;
  }

  public function changeAmount($productID, $qty = 1)
  {
	$products = array();

	$prod = Doctrine::getTable('Product')->find($productID);
	if ($prod['instock'] < $qty
	  )$qty = $prod['instock'];

	if ($this->getUser()->hasAttribute('basket.products'))
	{
	  $products = $this->getUser()->getAttribute('basket.products');
	}

	$products[$productID] = $qty;
	$this->getUser()->setAttribute('basket.products', $products);
  }

  public function isEmpty()
  {
	return $this->getProducts() ? false : true;
  }

  public function getTotalPrice()
  {
	$result = 0;
	foreach ($this->prepareDataForView() as $prod)
	  $result += $prod->getPrice();
	return $result;
  }

  private function setProducts(array $products)
  {
	$this->getUser()->setAttribute('basket.products', $products);
  }

  public function setDiscount($discount)
  {
	$this->getUser()->setAttribute('basket.discount', $discount);
  }

  public function setDiscountStatus($status)
  {
	$this->getUser()->setAttribute('discount.status', $status);
  }

  public function getDiscount()
  {
	return $this->getUser()->getAttribute('basket.discount');
  }

  public function getDiscountStatus()
  {
	return $this->getUser()->getAttribute('discount.status');
  }

  private function getUser()
  {
	return sfContext::getInstance()->getUser();
  }

  public function checkout()
  {

	$rawShippingdata = $this->getShippingAddress();
	$interval = $this->shippingZoneInterval();
	$shippingData = array(
	  'information' => $this->renderShippingAddress(),
	  'name' => $rawShippingdata['name'],
	  'cost' => $this->price(myBasket::SHIPPING_PRICE),
	  'mass_interval_start' => $interval['start'],
	  'mass_interval_end' => $interval['end'],
	  'vatrate' => 20
	);


	$rawBillingData = $this->getBillingAddress();
	$billingData = array(
	  'country' => $rawBillingData['country'],
	  'city' => $rawBillingData['city'],
	  'street' => $rawBillingData['address'],
	  'zip' => $rawBillingData['zip'],
	  'receiver' => $rawBillingData['name'],
	  'email' => $rawBillingData['email']
	);
	$pUser = $this->getUser()->getObject();
	if (!$pUser)
	{
	  $pUser = new PublicUser();
	  $pUser->setName('guest_' . sha1(time()));
	  $pUser->save();
	}
	$order = Doctrine::getTable('ProductOrder')->checkout(
			$this->getProducts(),
			$pUser,
			$this->getUser()->getCurrency(),
			$billingData,
			$shippingData
	);

	return $order;
  }

}

?>
